package app.itgungnir.compose.wan.widgets

import android.content.res.Configuration
import androidx.appcompat.app.AppCompatActivity
import androidx.compose.animation.animateContentSize
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.CircularProgressIndicator
import androidx.compose.material.Icon
import androidx.compose.material.MaterialTheme
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.CalendarToday
import androidx.compose.material.icons.outlined.ChevronRight
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties
import app.itgungnir.compose.wan.theme.WanComposePreviewTheme
import app.itgungnir.compose.wan.utils.toDateString
import com.google.android.material.datepicker.CalendarConstraints
import com.google.android.material.datepicker.MaterialDatePicker
import kotlinx.coroutines.Job
import java.util.*

@Composable
fun WanLoadingDialog(state: State<Boolean>, message: String = "Loading...", onDismiss: () -> Unit = {}) {
    if (state.value) {
        Dialog(
            onDismissRequest = {
                (state as? MutableState)?.value = false
                onDismiss.invoke()
            },
            properties = DialogProperties(dismissOnClickOutside = false)
        ) {
            WanLoadingDialogUI(message = message)
        }
    }
}

@Composable
private fun WanLoadingDialogUI(message: String = "Loading...") {
    Column(
        modifier = Modifier
            .width(250.dp)
            .background(MaterialTheme.colors.background, RoundedCornerShape(12.dp))
            .padding(vertical = 15.dp),
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        CircularProgressIndicator(modifier = Modifier.size(50.dp))
        Spacer(modifier = Modifier.height(10.dp))
        WanDescription(content = message, color = MaterialTheme.colors.primary)
    }
}

@Preview(name = "WanLoadingDialog light mode", showBackground = false)
@Preview(name = "WanLoadingDialog dark mode", uiMode = Configuration.UI_MODE_NIGHT_YES, showBackground = false)
@Composable
private fun WanLoadingDialogPreview() {
    WanComposePreviewTheme {
        WanLoadingDialogUI(message = "Test LoadingDialog message")
    }
}

@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun WanDialog(
    state: State<Boolean>,
    loadingJob: Job? = null,
    dismissState: State<Boolean>? = null,
    errorState: State<Throwable?>? = null,
    paddingValues: PaddingValues = PaddingValues(horizontal = 20.dp, vertical = 15.dp),
    content: @Composable ColumnScope.() -> Unit
) {
    if (state.value) {
        Dialog(
            onDismissRequest = {
                loadingJob?.cancel()
                (dismissState as? MutableState)?.value = false
                (errorState as? MutableState)?.value = null
                (state as? MutableState)?.value = false
            },
            properties = DialogProperties(dismissOnClickOutside = false, usePlatformDefaultWidth = false)
        ) {
            Column(
                modifier = Modifier
                    .padding(horizontal = 30.dp)
                    .fillMaxWidth()
                    .background(MaterialTheme.colors.background, RoundedCornerShape(12.dp))
                    .padding(paddingValues)
                    .animateContentSize()
            ) {
                content(this)
            }
        }
        LaunchedEffect(key1 = dismissState?.value) {
            if (dismissState?.value == true) {
                (state as? MutableState<Boolean>)?.value = false
            }
        }
    }
}

@Composable
fun WanDialogPreview(content: @Composable ColumnScope.() -> Unit) {
    WanComposePreviewTheme {
        Column(
            modifier = Modifier
                .padding(horizontal = 30.dp)
                .fillMaxWidth()
                .background(MaterialTheme.colors.background, RoundedCornerShape(12.dp))
                .padding(horizontal = 20.dp, vertical = 15.dp)
                .animateContentSize()
        ) {
            content(this)
        }
    }
}

@Composable
fun WanAlertDialog(
    state: State<Boolean>,
    title: String? = null,
    message: String,
    loadingState: State<Boolean> = mutableStateOf(false),
    loadingJob: Job? = null,
    dismissState: State<Boolean>? = null,
    errorState: State<Throwable?>? = null,
    negativeText: String = "取消",
    negativeCallback: () -> Unit = {},
    positiveText: String = "确定",
    positiveCallback: () -> Unit = {}
) {
    WanDialog(
        state = state,
        loadingJob = loadingJob,
        dismissState = dismissState,
        errorState = errorState,
        paddingValues = PaddingValues(top = 15.dp, bottom = 15.dp, start = 20.dp, end = 10.dp)
    ) {
        WanAlertDialogUI(
            title = title,
            message = message,
            loadingState = loadingState,
            errorState = errorState,
            negativeText = negativeText,
            negativeCallback = negativeCallback,
            positiveText = positiveText,
            positiveCallback = positiveCallback
        )
    }
}

@Composable
private fun WanAlertDialogUI(
    title: String? = null,
    message: String,
    loadingState: State<Boolean> = mutableStateOf(false),
    dismissState: State<Boolean>? = null,
    errorState: State<Throwable?>? = null,
    negativeText: String = "取消",
    negativeCallback: () -> Unit = {},
    positiveText: String = "确定",
    positiveCallback: () -> Unit = {}
) {
    if (title?.isNotEmpty() == true) {
        WanTitle(content = title)
    }
    Spacer(modifier = Modifier.height(15.dp))
    WanDescription(content = message)
    Spacer(modifier = Modifier.height(10.dp))
    Row(
        modifier = Modifier.fillMaxWidth(),
        horizontalArrangement = Arrangement.End,
        verticalAlignment = Alignment.CenterVertically
    ) {
        if (loadingState.value) {
            CircularProgressIndicator(
                modifier = Modifier
                    .padding(end = 15.dp)
                    .size(20.dp)
            )
        }
        WanTextButton(
            text = negativeText,
            color = MaterialTheme.colors.onBackground.copy(alpha = 0.6F),
            loadingState = loadingState
        ) {
            (errorState as? MutableState)?.value = null
            negativeCallback.invoke()
        }
        WanTextButton(text = positiveText, color = MaterialTheme.colors.primary, loadingState = loadingState) {
            (errorState as? MutableState)?.value = null
            positiveCallback.invoke()
        }
    }
    WanError(modifier = Modifier.padding(top = 5.dp), contentState = errorState)
}

@Preview(name = "TextureDialog light mode", showBackground = false)
@Preview(name = "TextureDialog dark mode", uiMode = Configuration.UI_MODE_NIGHT_YES, showBackground = false)
@Composable
private fun WanAlertDialogPreview() {
    WanComposePreviewTheme {
        Column(
            modifier = Modifier
                .padding(horizontal = 30.dp)
                .fillMaxWidth()
                .background(MaterialTheme.colors.background, RoundedCornerShape(12.dp))
                .padding(top = 15.dp, bottom = 15.dp, start = 20.dp, end = 10.dp)
                .animateContentSize()
        ) {
            WanAlertDialogUI(
                title = "Test TextureDialog title",
                message = "Test TextureDialog message, this message should be quite long to check its functionality.",
                negativeText = "No, thanks",
                negativeCallback = {},
                positiveText = "Yes, please",
                positiveCallback = {}
            )
        }
    }
}

@Composable
fun WanDatePickDialog(
    modifier: Modifier = Modifier,
    activity: AppCompatActivity,
    iconTintColor: Color = MaterialTheme.colors.onBackground,
    selectedDateValue: MutableState<Pair<Long, String?>?> = mutableStateOf(null),
    startCalendar: Calendar = Calendar.getInstance(),
    endCalendar: Calendar = Calendar.getInstance().apply { timeInMillis = 7289625599000L },
    loadingState: State<Boolean> = mutableStateOf(false)
) {
    fun showDatePicker() {
        activity.takeIf { !it.isDestroyed && !it.isFinishing }?.let { context ->
            val selectedMillis = selectedDateValue.value?.first ?: System.currentTimeMillis()
            val constraints = CalendarConstraints.Builder()
                .setStart(startCalendar.timeInMillis)
                .setOpenAt(selectedMillis)
                .setEnd(endCalendar.timeInMillis)
                .build()
            val picker = MaterialDatePicker.Builder.datePicker()
                .setCalendarConstraints(constraints)
                .setSelection(selectedMillis + 43200000L)
                .build()
            picker.show(context.supportFragmentManager, picker.toString())
            picker.addOnPositiveButtonClickListener {
                val calendar = Calendar.getInstance()
                calendar.timeInMillis = it
                selectedDateValue.value = it to it.toDateString()
            }
        }
    }
    Row(modifier = modifier, verticalAlignment = Alignment.CenterVertically) {
        val enabled = !loadingState.value
        Icon(imageVector = Icons.Filled.CalendarToday, contentDescription = "", tint = iconTintColor)
        Spacer(modifier = Modifier.width(15.dp))
        Row(
            modifier = Modifier
                .clip(shape = RoundedCornerShape(size = 5.dp))
                .background(color = MaterialTheme.colors.surface)
                .then(if (enabled) Modifier.clickable { showDatePicker() } else Modifier)
                .padding(horizontal = 10.dp, vertical = 5.dp),
            verticalAlignment = Alignment.CenterVertically
        ) {
            WanDescription(content = selectedDateValue.value?.second ?: "请选择日期")
            Icon(
                imageVector = Icons.Outlined.ChevronRight,
                contentDescription = "",
                tint = MaterialTheme.colors.onSurface
            )
        }
    }
}

@Preview(name = "WanDatePickDialog light mode", showBackground = true)
@Preview(name = "WanDatePickDialog dark mode", uiMode = Configuration.UI_MODE_NIGHT_YES, showBackground = true)
@Composable
private fun WanDatePickDialogPreview() {
    WanComposePreviewTheme {
        WanDatePickDialog(activity = AppCompatActivity())
    }
}
